<?php
class Arm_Db_Table_Abstract extends Zend_Db_Table_Abstract{

    public $i18n = False;

    protected $_rowClass    = 'Arm_Db_Table_Row_Abstract';

    protected $_where = Array();
    protected $_joins = Array();

    // Nome da classe para uso em sistemas genericos
    public $verbose_name = 'Verbose name not implemented';

    // Url da página de documentação
    public $docUrl       = False;

    public function fetchAll($where = null, $order = null, $count = null, $offset = null){
            
        if(($where instanceof Zend_Db_Select) AND !($where instanceof Zend_Db_Table_Select)){
             
            $rows = $where->query()->fetchAll();
            return $this->getRowset($rows);
        }else{
            return parent::fetchAll($where, $order, $count, $offset);
        }
    }

    public function makeJoin($reference){
    
        $ref    = $this->_referenceMap[$reference];
        $model  = new $ref['refTableClass'];

        if(is_array($ref['columns'])){
            $i    = 0;
            $join = '';
            foreach($ref['columns'] as $column){
                if($i) $join .= ' AND ';
                $join .= "{$this->_name}.{$column} = {$model->getName()}.{$ref['refColumns'][$i]}";
                $i++;
            }
        }else{
            $join = "{$this->_name}.{$ref['columns']} = {$model->getName()}.{$ref['refColumns']}";
        }

        return $join;
    }

    public function getIndex(){
    
        $index = array();
        foreach($this->_referenceMap as $reference){
            $columns = $reference['columns'];
            if(is_array($columns)){
                $index = array_merge($index,$columns);
            }else{
                array_push($index,$columns);
            }
        }
        return $index;
    }
    
    public function getRef($name){
    
        return $this->_referenceMap[$name];
    }
    
    public function getReferences(){
    
        return $this->_referenceMap;
    }

    public function getDependents(){
    
        return $this->_dependentTables;
    }

    public function getWhere(){
        
        return $this->_where;
    }

    public function merge(){
     
        $references  = func_get_args();
        $joins       = array();

        $this->_dependentTables['_merge'] = array();

        foreach($references as $reference){
           
            $s     = explode('.',$reference);
            $model = $this;   
            $tam   = count($s);
            for($i = 0; $i < $tam; $i++){
                
                $ref    = $model->getRef($s[$i]);
                if($tam - 1 == $i) {
                    $join = $model->makeJoin($s[$i]);
                }
                $model  = new $ref['refTableClass'];
                $this->_referenceMap    = array_merge($this->_referenceMap,$model->getReferences());
                $this->_dependentTables = array_merge($this->_dependentTables,$model->getDependents());
                $this->_where           = array_merge($this->_where, $model->getWhere());
                
                $this->_dependentTables['_merge'][$ref['refTableClass']] = array_keys($model->getDependents());
            }
             
            $this->_joins[] = array(array($model->getName() => $model->getPath()),$join,$model->getIndex());
        }
    }

    public function getName(){
        return $this->_name;
    }

    public function getPath(){
        return $this->_schema .".". $this->_name;
    }
    
    public function addWhere($field,$value){
    
        $this->_where[] = "{$this->_name}.{$field} = {$value}";
    }

    public function addWhereByParent(Arm_Db_Table_Row_Abstract $parent,$origin = null){
        
        $table     = is_null($origin) ? get_class($parent->_class_table) : $origin;
        $reference = $this->getReference($table);

        if(is_null($reference)){
            throw new Zend_Exception("Nenhuma referencia de {$origin} para " . get_class($parent->getTable()));
        }else{
            $i = 0;
            foreach($reference['columns'] as $column){
                $this->addWhere($column,$parent->$reference['refColumns'][$i]);
                $i++;
            }
        }
    }

    public function getRowset($rows = array()){
    
        $data  = array(
            'table'    => $this,
            'data'     => $rows,
            'rowClass' => $this->getRowClass(),
            'stored'   => true
        );
        
        $rowsetClass = $this->getRowsetClass();
        if (!class_exists($rowsetClass)) {
            require_once 'Zend/Loader.php';
            Zend_Loader::loadClass($rowsetClass);
        }

        return new $rowsetClass($data);
    }


    /**
     *  Verifica se o objeto possui a coluna informada.
     *  @param  string  $column
     *  @return boolean
     */
    public function hasColumn($column){
        $info       = $this->info();
        $columns    = $info['cols'];

        return in_array($column, $columns);
    }
}
